/**
 * WTF Engine
 *
 * License... etc.
 **
 * AI Behaviours - Base Classes
 *
 * Provides base classes for AI behaviours.
 **
 * Author: Sean Micklethwaite
 **/

#ifndef __ai_behaviourH__
#define __ai_behaviourH__

#include <vector>
#include <typeinfo>
#include "data.h"
#include "world.h"

namespace WtfEngine
{
	/**
	 * Behaviours represent small segments of an AI's cognitive process.
	 * They can be chained together and composed (subject to having
	 * compatible preconditions and postconditions) to build more complex
	 * and rich behaviours out of simple components.
	 * 
	 * Each behaviour takes input of a certain data class (preconditions, and
	 * optional conditions), performs some processing and actions, and optionally
	 * returns some new data to be piped to another behaviour.
	 **/
	class Behaviour : public DataObject
	{
	public:
		Behaviour(const StringPool::Entry& sName): DataObject(sName) {
		};

		DATA_OBJECT(Behaviour, sizeof(Behaviour));
	};

	/**
	 * AI Models are simply behaviours which take and return no parameters, such that they
	 * can be invoked as the first behaviour on an actor.
	 **/
	class AiModel: public Behaviour {
		DATA_OBJECT(AiModel, sizeof(AiModel));

	public:
		AiModel(const StringPool::Entry& sName = "Identity AI Model"): Behaviour(sName) {
		};

		virtual bool Evaluate(const IActor::tRef& rActor) {
			return true;
		};
	};


	/**
	 * Decorators wrap an AiModel and add additional logic.
	 **/
	class Decorator: public AiModel {
	private:
		AiModel::tRef	mrBaseAiModel;

		DATA_OBJECT(Decorator, sizeof(Decorator));

	public:
		inline Decorator(const StringPool::Entry& sName, const AiModel::tRef& rBaseAiModel):
		AiModel(sName), mrBaseAiModel(rBaseAiModel) {
		};

		virtual bool Evaluate(const IActor::tRef& rActor) {
			return mrBaseAiModel->Evaluate(rActor);
		};

		inline const AiModel::tRef& getBaseAiModel() const {
			return mrBaseAiModel;
		};
		inline void setBaseAiModel(const AiModel::tRef& rBaseAiModel) {
			mrBaseAiModel = rBaseAiModel;
		};
	};


	class IMobileActor: public virtual IActor {
		GC_INTERFACE(IMobileActor);

		public:
			virtual tDirection	getVelocity() const = 0;
			virtual void		setVelocity(const tDirection& v) = 0;

			virtual tPosition	getGoalPosition() const = 0;
			virtual tScalar		getGoalRadius() const = 0;
	};

	namespace Behaviours {

		/**
		 * Goal motion behaviours take a goal position and return a desired velocity
		 * to reach the goal. The default heads straight towards the goal.
		 * This is subclassed to provide collision avoidance and crowd dynamics.
		 **/
		class GoalMotion: public Behaviour {
		public:
			GoalMotion(const StringPool::Entry& sName): Behaviour(sName) {};

			virtual bool Evaluate(const IMobileActor::tRef& rActor, const tPosition& vGoal, tDirection& vDesiredVelocity) {
				vDesiredVelocity = vGoal - rActor->getPosition();
				return true;
			};


			// Even though this provides a full implementation, it is still a base class, so keep the references
			// polymorphic.
			DATA_OBJECT(GoalMotion, sizeof(GoalMotion));
		};

		/**
		 * Motion control behaviours take a desired velocity and invoke actions on the actor in order to
		 * modify the velocity to the desired one. The default simply sets the velocity directly.
		 **/
		class MotionControl: public Behaviour {
		public:
			MotionControl(const StringPool::Entry& sName): Behaviour(sName) {};

			virtual bool Evaluate(const IMobileActor::tRef& rActor, const tDirection& vDesiredVelocity) {
				rActor->setVelocity(vDesiredVelocity);
				return true;
			};

			// See above.
			DATA_OBJECT(MotionControl, sizeof(MotionControl));
		};
	};
};

#endif
